/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MetricsRetriever;

import General.Globals;
import General.RequestMaker;
import SVNSupport.SVNManager;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.tmatesoft.svn.core.SVNLogEntry;
/**
 *
 * @author Manuel
 */
public class GoogleRetriever extends Retriever{

    private SVNManager svnManager;

    public GoogleRetriever(DataManager dm){
        super(dm);
        this.forgeName = "http://code.google.com";
        svnManager = new SVNManager();
    }


    //extracts project name, description, language and similars from the html source
    public void retrieveContextData() {
        currentProject.setUrl(this.currentLink);
        currentProject.setForge("googlecode");
        currentProject.setName(this.parseCharacterData("/p/","/",this.currentLink,false,true));
        currentProject.setDescription(this.parseCharacterData("<td id=\"wikicontent\" class=\"psdescription\">","</td>",this.currentPage,true,true));
        this.retrieveLabels();
        this.retrieveCollaborators(RequestMaker.getPage(currentLink+"people/list"));
        this.retrieveActivityLevel();

    }

    //complex algorithm to choose the right release/package which contains the bytecode
    public ProjectPackage selectArchieveLink() {

        //parse the download page to find the right download links
        //list all downloads define algorithm to rank them
        String projectURL = this.currentProject.getUrl();
        String projectName = this.currentProject.getName();
        String link = "";
        ArrayList<ProjectPackage> candidateLinks = new ArrayList<ProjectPackage>();
        String downloadsPage = RequestMaker.getPage(projectURL+"downloads/list?can=1&colspec=Filename+Summary+Uploaded+Size+DownloadCount");
        if(downloadsPage.isEmpty())
            return null;
        //detect in which column in which the size of the file is given
        String sizeColumn = "4";
        int colStartIndex = downloadsPage.indexOf("var _allColumnNames = [");
        int colEndIndex = downloadsPage.toLowerCase().indexOf("size",colStartIndex);
        if(colStartIndex > -1 && colEndIndex > -1){
            String columns = downloadsPage.substring(colStartIndex,colEndIndex);
            sizeColumn = Integer.toString(columns.replaceAll("[^,]", "").length());
        }

        //detect the column in which the number of downloads is given

        String countColumn = "5";
        int couStartIndex = downloadsPage.indexOf("var _allColumnNames = [");
        int couEndIndex = downloadsPage.toLowerCase().indexOf("downloadcount",couStartIndex);
        if(couStartIndex > -1 && couEndIndex > -1){
            String columns = downloadsPage.substring(couStartIndex,couEndIndex);
            countColumn = Integer.toString(columns.replaceAll("[^,]", "").length());
        }

        //       N   O   W             R   E    T  R   I   E    V   E            A L L         L I N K S
        //cut out relevant part of html
        downloadsPage = parseCharacterData("id=\"resultstable\" width=\"100%\">","</table>",downloadsPage,false,true);

        //check through all links and retrieve user id
        ProjectPackage currentPackage;
        int instances = 0;
        long totalSize = 0;
        int avgSize = 0;
        long totalDownloads = 0;
        int avgDownloads = 0;
        String typeTag ="";
        int nextLink = downloadsPage.indexOf("href=");
        String originalPage = downloadsPage;
        downloadsPage = downloadsPage.toLowerCase();

        while(nextLink >= 0){
            currentPackage = new ProjectPackage(projectName);
            int nextRef = downloadsPage.indexOf("\"", nextLink) + 1;
            int endRef = downloadsPage.indexOf("\"", nextRef);
            int nextTypeTag = downloadsPage.indexOf("onclick",endRef);
            int endTypeTag = downloadsPage.indexOf("\"",nextTypeTag + 10);
            int endOfLink = downloadsPage.indexOf("</tr>",nextRef);

            // get the name
            if(nextRef>0 && endRef > 0)
                currentPackage.setName(originalPage.substring(nextRef,endRef));



            //check link and eventually add it to the list
            boolean isInterestingLink =  currentPackage.getName().endsWith(".tar.bzip2") || currentPackage.getName().endsWith(".tbz2") || currentPackage.getName().endsWith(".tar.bz2") || currentPackage.getName().endsWith(".tar.gzip") || currentPackage.getName().endsWith(".tgz") || currentPackage.getName().endsWith(".tar.gz") || currentPackage.getName().endsWith("zip") || currentPackage.getName().endsWith(".tar") || currentPackage.getName().endsWith(".jar") || currentPackage.getName().endsWith(".class");

            if(isInterestingLink){
                    //get the description
                    if(nextTypeTag>0 && endTypeTag>0)
                        typeTag = downloadsPage.substring(nextTypeTag,endTypeTag);
                    String description = parseCharacterData("href=","</tr>",downloadsPage,true,true);
                    currentPackage.setDescription(description);

                    //set the featuring
                    if(typeTag.contains("featured"))
                        currentPackage.setFeatured(true);

                    //get the size
                    String size = parseCharacterData("<td class=\"vt col_"+sizeColumn+"\"","</td>",downloadsPage,true,false);
                    size = size.replaceAll(" ", "");
                    long sizeNo = 0;
                    if(size.contains("mb")){
                        double dec = Double.parseDouble(size.replaceAll("mb", ""));
                        dec *= 1000000;
                        sizeNo = Math.round(dec);
                    }
                    else if(size.contains("kb")){
                        double dec = Double.parseDouble(size.replaceAll("kb", ""));
                        dec *= 1000;
                        sizeNo = Math.round(dec);
                    }
                    else if(size.contains("bytes"))
                        sizeNo = (long) Integer.parseInt(size.replaceAll("bytes", ""));
                    currentPackage.setSize(sizeNo);

                    //get the number of downloads
                    String downloadString = parseCharacterData("<td class=\"vt col_"+countColumn+"\"","</td>",downloadsPage,true,false).replaceAll( "[^\\d]", "" );

                    int downloads = -1;
                    if(!downloadString.isEmpty()){
                        downloads = (int) Integer.parseInt(downloadString.replaceAll(" ", ""));
                    }
                    currentPackage.setDownloadNumber(downloads);

                    //get the date
                    String filteredName = currentPackage.getName().substring(currentPackage.getName().lastIndexOf("/")+1);
                    String pageDate = RequestMaker.getPage("http://code.google.com/p/"+projectName+"/downloads/detail?name="+filteredName);
                    if(pageDate.isEmpty())
                        return null;
                    String theDate = parseCharacterData("<span class=\"date\" style=\"white-space:nowrap\"","</span>",pageDate,true,false);
                    DateFormat df = DateFormat.getDateInstance();
                    Date myDate = null;
                    try {
                        myDate = df.parse(theDate);
                    } catch (Exception ex) {}
                    currentPackage.setDate(myDate);

                    //add to the list if sufficient data is obtainable
                    if(myDate != null && currentPackage.getDownloadNumber() != -1 ){
                        instances++;
                        totalSize += currentPackage.getSize();
                        totalDownloads += currentPackage.getDownloadNumber();
                        candidateLinks.add(currentPackage);
                    }
            }

            downloadsPage = downloadsPage.substring(downloadsPage.indexOf("</tr>",endRef));
            originalPage = originalPage.substring(originalPage.indexOf("</tr>",endRef));
            nextLink = downloadsPage.indexOf("href=");

        }

        //identifying the most probable package
        if(instances != 0){
            avgSize = (int) (totalSize / instances);
            avgDownloads = (int) (totalDownloads / instances);
        }

        ProjectPackage winner = null;
        int maxScore = -100000;
        Date maxDate = new Date(1,1,0);
        for(int i = 0;i<candidateLinks.size();i++){
            candidateLinks.get(i).rank(avgSize,avgDownloads);
            ProjectPackage pp = candidateLinks.get(i);
            if(pp.getRank()>maxScore){
                winner = pp;
                maxScore = pp.getRank();
                maxDate = pp.getDate();
            }
            if(pp.getRank()==maxScore && pp.getDate().after(maxDate)){
                winner = pp;
                maxDate = pp.getDate();
            }
        }
        if(winner == null)
            return null;
        return winner;
    }




    //SUBMETHODS FOR RETRIEVAL OF CONTEXTUAL INFORMATION
    private void retrieveLabels() {
        String labelString = this.parseCharacterData("<b>Labels</b><br/>",  "</span>",this.currentPage,true,true);
        labelString = labelString.replaceAll(" ","");
        ArrayList<String> labels = new ArrayList<String>();

        while(labelString.indexOf(",") != -1 ){
            labels.add(labelString.substring(0,labelString.indexOf(",")));
            labelString = labelString.substring(labelString.indexOf(",")+1);
        }
        String currentLabel;
        for(int i = labels.size()-1;i>=0;i--){
            currentLabel = labels.get(i).toLowerCase();
            currentProject.addLabel(currentLabel);
            if(currentLabel.equals("java") || currentLabel.equals("c") || currentLabel.equals("cplusplus") || currentLabel.equals("python") )
                currentProject.addLanguage(currentLabel);
        }
    }

    private void retrieveCollaborators(String userPage) {

        //cut out relevant part of html
        userPage = parseCharacterData("<b>Project People</b>","</tbody>",userPage,false,true);

        //check through all links and retrieve user id
        String currentCollaborator = "";
        int nextLink = userPage.indexOf("href=");
        userPage = userPage.toLowerCase();

        while(nextLink >= 0){
            int nextRef = userPage.indexOf("\"", nextLink) + 1;
            int endRef = userPage.indexOf("\"", nextRef);
            if(nextRef < 0 || endRef < 0)
                break;
            currentCollaborator = userPage.substring(nextRef,endRef);
            int colStart = currentCollaborator.indexOf("/people/detail?u=");
            int tagLength = "/people/detail?u=".length();
            if(colStart < 0 )
                break;
            currentCollaborator = currentCollaborator.substring(colStart+tagLength);
            userPage = userPage.substring(endRef);
            nextLink = userPage.indexOf("href=");
            currentProject.addCollaboratorIfNew(currentCollaborator);
        }

    }
    
    public void retrieveActivityLevel(){
        String level = this.parseCharacterData("class=\"activity-level-", "\"", this.currentPage,true,true);
        if(level.equals("high"))
            currentProject.setActivity(3);
        else if(level.equals("medium"))
            currentProject.setActivity(2);
        else if(level.equals("low"))
            currentProject.setActivity(1);
        else
            currentProject.setActivity(0);
    }

    public String selectRepositoryLink(){
        String repoLink = "";
        String repoPage = RequestMaker.getPage(currentProject.getUrl()+"source/checkout");

        // if it is SVN
        if(repoPage.contains("svn checkout")){
            String command = this.parseCharacterData("svn checkout", "</tt>", repoPage, true, true);
            int startIndex = command.indexOf("http");
            int endIndex = command.indexOf(" ",startIndex);
            String url = command.substring(startIndex,endIndex);
            repoLink = "svn"+url;
        }

        return repoLink;
    }

}
